﻿using System;
using System.Security.Cryptography.X509Certificates;
using System.Web;
using System.Web.SessionState;
using Microsoft.IdentityModel.Protocols.WSFederation;
using Microsoft.IdentityModel.SecurityTokenService;
using Microsoft.IdentityModel.Web;
using Microsoft.SharePoint;

namespace CodeCounsel.SharePoint2010.DigiD
{
    public class DigiDHandler 
        : IHttpHandler, IRequiresSessionState
    {
        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext context)
        {
            // Parse the request URI into an object.
            AuthenticationMessage authenticateResponse = AuthenticationMessage.CreateFromUri(context.Request.Url);
            // The DigiD request ID is used as the cache key for getting the SharePoint STS request.
            SignInRequestMessage requestMessage = SignInRequestCache.Get(authenticateResponse.RequestID);
            // The identifier 'realm' are passed in the incoming SharePoint STS request cached earlier.
            DigiDSettings settings = DigiDService.Local.DigiDSettings[requestMessage.Realm];
            if (settings == null)
            {
                throw new DigiDException("Realm is not configured for DigiD authentication.");
            }
            // Call DigiD to verify the data presented by the user
            VerifyWebRequest request = new VerifyWebRequest(
                authenticateResponse.RequestID,
                authenticateResponse.Credentials,
                authenticateResponse.ServerID, settings);
            // The response is auto-validated for result code and applied security level
            VerifyWebResponse response = request.GetResponse();
            // Build a configuration object for the Windows Identity Framework STS instance
            DigiDSecurityTokenServiceConfiguration configuration =
                new DigiDSecurityTokenServiceConfiguration(
                    DigiDService.Local.IssuerName, // The token issuer name
                    DigiDService.Local.GetSigningCertificate()); // The certificate to sign the tokens with
            // The STS adds claims
            SecurityTokenService sts = new DigiDSecurityTokenService(
                configuration, // The issuer / signing data
                response.UserID); // needed for adding the BSN number claim, 
            // Handle the STS request and add claims
            SignInResponseMessage responseMessage = FederatedPassiveSecurityTokenServiceOperations.ProcessSignInRequest(
                requestMessage, context.User, sts);
            // Redirect the user back to his origin
            FederatedPassiveSecurityTokenServiceOperations.ProcessSignInResponse(
                responseMessage, context.Response);
        }
    }
}
